package smallfrench.ui;

import java.awt.event.ActionEvent;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;

import javax.swing.AbstractAction;
import javax.swing.JMenu;
import javax.swing.JMenuItem;

/**
 * Permet de gérer une arborescence d'exemples.
 * @author antoine1023
 *
 */
public class Exemples {

	private Exemples() {}

	private static DossierExemple dossier = new DossierExemple(
			"Exemples", "exemples");

	private static DossierExemple dossierAvance = new DossierExemple(
			"Avancé", "avance");

	private static DossierExemple dossierPoo = new DossierExemple(
			"Programmation orientée objet", "poo");

	private static DossierExemple dossierDebutant = new DossierExemple(
			"Débutant", "debutant");

	private static DossierExemple dossierIGU = new DossierExemple(
			"Interface graphique utilisateur", "igu");

	static {

		dossierDebutant.ajouter(new Exemple(
				"Bonjour, Monde !", "bonjour_monde"));
		dossierDebutant.ajouter(new Exemple("Calculs simples", "calculs"));
		dossierDebutant.ajouter(new Exemple("Variables", "variables"));
		dossierDebutant.ajouter(new Exemple("Boucles", "boucles"));
		dossierDebutant.ajouter(new Exemple(
				"Branchements conditionnels", "conditions"));
		dossierDebutant.ajouter(new Exemple(
				"Utilisation de fonctions", "fonctions"));
		dossierDebutant.ajouter(new Exemple(
				"Utilisation de la console", "console"));
		dossierDebutant.ajouter(new Exemple(
				"Fonctions mathématiques", "fonctions_mathematiques"));
		dossierDebutant.ajouter(new Exemple("Tableaux", "tableaux"));

		dossier.ajouter(dossierDebutant);

		//----------------------------------------------------

		dossierAvance.ajouter(new Exemple("Décorateurs", "decorateurs"));
		dossierAvance.ajouter(new Exemple(
				"Fermetures lexicales", "fermetures"));
		dossierAvance.ajouter(new Exemple("Jeu du pendu", "pendu"));
		dossierAvance.ajouter(new Exemple("Casse briques", "casse_briques"));
		dossierAvance.ajouter(new Exemple("Snake", "snake"));

		dossier.ajouter(dossierAvance);

		//----------------------------------------------------

		dossierPoo.ajouter(new Exemple("Interpréteur", "interp"));

		dossier.ajouter(dossierPoo);


		//----------------------------------------------------

		dossierIGU.ajouter(new Exemple("Majeur / mineur", "majeur_mineur"));

		dossier.ajouter(dossierIGU);

		dossier.ajouter(new Exemple("Factorielle", "factorielle"));
		dossier.ajouter(new Exemple(
				"Tri, méthode de la bulle", "tri_bulle"));
	}

	/**
	 * @param fp
	 * @return Un nouveau sous-menu contenant les exemples
	 */
	public static JMenu getMenu(FenetrePrincipale fp) {
		return getMenu(fp, dossier);
	}

	/**
	 * @param fp
	 * @param dossier
	 * @return Un nouveau sous-menu contenant les exemples
	 */
	public static JMenu getMenu(FenetrePrincipale fp,
			DossierExemple dossier) {

		JMenu menu = new JMenu(dossier.getNom());
		JMenuItem item;

		for (Exemple f : dossier.getExemples()) {
			if (f instanceof DossierExemple) {
				menu.add(getMenu(fp, (DossierExemple)f));
			} else {
				item = new JMenuItem(
						new ActionOuvrirExemple(f, fp)
						);
				menu.add(item);
			}
		}
		return menu;
	}

	/**
	 * Lis un fichier dans le JAR
	 * @param nom
	 * @return Contenu du fichier.
	 * @throws IOException
	 * @throws UnsupportedEncodingException
	 */
	private static String lireFichierEmbarque(String nom)
			throws UnsupportedEncodingException, IOException {

		InputStream stream = FenetrePrincipale.class.getResourceAsStream(nom);

		if (stream == null) {
			throw new FileNotFoundException(
					"Fichier \"" + nom + "\" non trouvé");
		}

		return Ressources.lireFluxUTF8(stream);
	}

	//	private static String enleverExtension(String nom) {
	//		int i = nom.lastIndexOf('.');
	//		if (i != -1) {
	//			return nom.substring(0, i);
	//		}
	//		return nom;
	//	}

	@SuppressWarnings("serial")
	private static class ActionOuvrirExemple extends AbstractAction {

		private Exemple fichier;
		private FenetrePrincipale fp;

		public ActionOuvrirExemple(Exemple fichier, FenetrePrincipale fp) {
			super(fichier.getNom());
			this.fichier = fichier;
			this.fp = fp;
		}

		@Override
		public void actionPerformed(ActionEvent event) {
			try {
				String s = lireFichierEmbarque(fichier.getAdresse());
				fp.ouvrirFichierExemple(s);

			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	/**
	 * Fichier d'exemple
	 */
	private static class Exemple {
		private String nom;
		protected String adresse;
		protected DossierExemple parent;

		public Exemple(String nom, String adresse) {
			parent = null;
			this.nom = nom;
			this.adresse = adresse;
		}

		public String getNom() {
			return nom;
		}

		public String getAdresse() {
			return (parent == null ? "" : parent.getAdresse()) + adresse +
					".sfrench";
		}

		public void setParent(DossierExemple parent) {
			this.parent = parent;
		}
	}

	/**
	 * Dossier d'exemple
	 */
	private static class DossierExemple extends Exemple {
		private ArrayList<Exemple> exemples;

		public DossierExemple(String nom, String adresse,
				ArrayList<Exemple> exemples) {
			super (nom, adresse);
			this.exemples = exemples;
		}

		public DossierExemple(String nom, String adresse) {
			this(nom, adresse, new ArrayList<Exemple>());
		}

		public Exemple[] getExemples() {
			return exemples.toArray(new Exemple[exemples.size()]);
		}

		public void ajouter(Exemple e) {
			exemples.add(e);
			e.setParent(this);
		}

		@Override
		public String getAdresse() {
			return (parent == null ? "" : parent.getAdresse()) +
					adresse + "/";
		}
	}
}
